home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / step13.arc / STEP13.ASM < prev    next >
Encoding:
Assembly Source File  |  1988-03-19  |  48.1 KB  |  1,758 lines

  1.  
  2.         PAGE    60,132
  3.         TITLE   'Step INT 13H Calls'
  4.         NAME    STEP13
  5. ;
  6. ;       ***********************************************************
  7. ;       *                                                         *
  8. ;       *                    S  T  E  P  1  3                     *
  9. ;       *                                                         *
  10. ;       *                        Rev 1.0                          *
  11. ;       *                                                         *
  12. ;       *                      Nov 20, 1987                       *
  13. ;       *                                                         *
  14. ;       *                      Mike Parker                        *
  15. ;       *                 2374 Meadowpark Court                   *
  16. ;       *               Maryland Heights, MO 63043                *
  17. ;       *                                                         *
  18. ;       *                     CIS 70270,161                       *
  19. ;       *                                                         *
  20. ;       * STEP13 intercepts BIOS INT 13h calls and displays a     *
  21. ;       * window that shows the function being called and the     *
  22. ;       * parameters being passed to it. Program execution will   *
  23. ;       * resume when a key is pressed. This allows you to single *
  24. ;       * step through accesses to the disk at the BIOS level.    *
  25. ;       *                                                         *
  26. ;       * STEP13 can be activated and de-activated through key-   *
  27. ;       * board commands.                                         *
  28. ;       *                                                         *
  29. ;       ***********************************************************
  30. ;
  31. ;
  32. ;
  33. TESTING    EQU    0
  34.  
  35. BG         EQU    10H               ; BG sets background color (10h = BLUE)
  36.  
  37. BLACK      EQU    00H + BG
  38. BLUE       EQU    01H + BG
  39. GREEN      EQU    02H + BG
  40. CYAN       EQU    03H + BG
  41. RED        EQU    04H + BG
  42. MAGENTA    EQU    05H + BG
  43. BROWN      EQU    06H + BG
  44. WHITE      EQU    07H + BG
  45. GRAY       EQU    08H + BG
  46. LTBLUE     EQU    09H + BG
  47. LTGREEN    EQU    0AH + BG
  48. LTCYAN     EQU    0BH + BG
  49. LTRED      EQU    0CH + BG
  50. LTMAGENTA  EQU    0DH + BG
  51. YELLOW     EQU    0EH + BG
  52. HIWHITE    EQU    0FH + BG
  53. ;
  54. CR         EQU    13
  55. LF         EQU    10
  56. BIGR       EQU    1352H             ; 'R' key
  57. SMALLR     EQU    1372H             ; 'r'
  58. BIGS       EQU    1F53H             ; 'S' key
  59. SMALLS     EQU    1F73H             ; 's'
  60. ESCAPE     EQU    011BH
  61. HOME       EQU    4700H
  62. UPARROW    EQU    4800H
  63. PGUP       EQU    4900H
  64. LEFTARROW  EQU    4B00H
  65. RIGHTARROW EQU    4D00H
  66. XEND       EQU    4F00H
  67. DOWNARROW  EQU    5000H
  68. PGDN       EQU    5100H
  69. ;
  70. BLANK      EQU    32
  71. BRDROW     EQU    205
  72. BRDCOL     EQU    186
  73. ULC        EQU    201
  74. URC        EQU    187
  75. LLC        EQU    200
  76. LRC        EQU    188
  77. ;
  78. REGBX      EQU    00                ; offsets on saved register stack
  79. REGCX      EQU    02
  80. REGDX      EQU    04
  81. REGDI      EQU    06
  82. REGSI      EQU    08
  83. REGBP      EQU    10
  84. REGES      EQU    12
  85. ;
  86. ; Format of Step_Flg
  87. ;
  88. STOP      EQU    01                  ; stop and display if bit 0 = 1
  89. TERM      EQU    02                  ; terminate STEP13 if bit 1 = 1
  90. ;
  91. IF TESTING
  92. INT13OFF   EQU    0e0h*4            ; during testing an unused INT is used
  93. ELSE
  94. INT13OFF   EQU    13h*4
  95. ENDIF
  96.  
  97. INT1cOFF   EQU    1ch*4
  98. INT28OFF   EQU    28h*4
  99.  
  100. Code    SEGMENT PUBLIC PARA 'CODE'
  101.  
  102.         ASSUME  CS:Code, DS:Code
  103.  
  104.         ORG     100h
  105.  
  106. Main:                               ; starting point
  107.         jmp     SHORT Main_1
  108.  
  109. Res_Str db      'STEP13'            ; Resident ID string to determine if
  110.         db      0                   ;  already resident
  111. ;
  112. Main_1:
  113.         cli
  114.         cld
  115.         mov     AX,CS
  116.         mov     SS,AX
  117.         mov     SP,OFFSET Pstack
  118.         mov     BX,DS               ; get difference between segments
  119.         sub     AX,BX               ;  so .EXE file can run during testing
  120.         sti
  121. ;
  122.         mov     BX,OFFSET PRSIZE    ; program size in bytes
  123.         mov     CL,4
  124.         shr     BX,CL               ; convert it to paragraphs
  125.         add     BX,AX               ; add difference between segments
  126.         inc     BX                  ; make it next multiple of 16 bytes
  127.         mov     CX,BX               ; CX = number paragraphs in this program
  128.                                     ;  offset from PSP base
  129. ;
  130.         mov     BX,002ch
  131.         mov     BX,[BX]             ; get segment addr of environment from PSP
  132. ;
  133.         mov     AX,CS
  134.         mov     DS,AX               ; change DS and ES to local area
  135.         mov     SegPSP,ES           ; save starting segment to release later
  136.         mov     ES,AX
  137.         mov     SegEnv,BX           ; save environment segment to release also
  138.         mov     SegEND,CX           ; now save CX
  139. ;
  140. ; Now that segment registers are all in order see if this program is already
  141. ; resident by finding out who currently has INT 13h.
  142. ; Get segment of the program and look for ID string found at start of this
  143. ; program.
  144. ;
  145.         push    ES
  146.         mov     AL,13h
  147.         mov     AH,35h
  148.         int     21h                 ; return address in ES:BX
  149.         call    Cmp_Str             ; search for ID string
  150.         pop     ES
  151.         jnz     chkeq               ; not found, continue
  152. ;
  153. ; This program already installed
  154. ;
  155.         mov     DX,OFFSET ERRmsg
  156.         mov     AH,9
  157.         int     21h
  158. ;
  159.         mov     AH,4ch              ; terminate (without staying resident)
  160.         mov     AL,00
  161.         int     21h
  162.  
  163. ;
  164. ; Check equipment list to see if we have graphics or monochrome card
  165. ;
  166. chkeq:
  167.         int     11h
  168.         and     AX,0030h            ; save video mode
  169.         mov     BX,0b000h
  170.         cmp     AX,0030h            ; monochrome?
  171.         jz      setcrd
  172.         mov     BX,0b800h           ; no, graphics card
  173. setcrd:
  174.         mov     Scrseg,BX           ; save base segment
  175. ;
  176. ; Calculate starting address on screen for window
  177. ;
  178.         mov     BX,OFFSET W1        ; window parameters
  179.         call    Window_Parms        ; calc start addr of window, wid and ht
  180. ;
  181. ; Make room for window save area - AX is number of bytes needed for window
  182. ;
  183.         mov     CL,4
  184.         shr     AX,CL               ; divide by 16 to get # paragraphs
  185.         inc     AX                  ; handle any remainder
  186.         mov     BX,SegPSP           ; starting PSP segment
  187.         add     BX,SegEND           ; size of program in paragraphs
  188.         mov     Winseg,BX           ; starting segment of window save area
  189.         add     SegEND,AX           ; expand total space needed by this
  190.                                     ;  programs code and window save area
  191. ;
  192. ; Redirect INT 13h, INT 28h and INT 1ch
  193. ;
  194.         push    ES
  195.         cli
  196.         mov     AX,0
  197.         mov     ES,AX
  198.         mov     AX,OFFSET New13
  199.         xchg    AX,ES:[INT13OFF]
  200.         mov     Save13,AX
  201.         mov     AX,CS
  202.         xchg    AX,ES:[INT13OFF+2]
  203.         mov     Save13+2,AX
  204.  
  205. IFE TESTING
  206.         mov     AX,OFFSET New1c
  207.         xchg    AX,ES:[INT1cOFF]
  208.         mov     Save1c,AX
  209.         mov     AX,CS
  210.         xchg    AX,ES:[INT1cOFF+2]
  211.         mov     Save1c+2,AX
  212. ;
  213.         mov     AX,OFFSET New28
  214.         xchg    AX,ES:[INT28OFF]
  215.         mov     Save28,AX
  216.         mov     AX,CS
  217.         xchg    AX,ES:[INT28OFF+2]
  218.         mov     Save28+2,AX
  219. ENDIF
  220.  
  221.         sti
  222.         pop     ES
  223. ;
  224.         mov     DX,OFFSET INITmsg
  225.         mov     AH,9
  226.         int     21h
  227.  
  228. IF TESTING
  229.         mov     SP,OFFSET Tstack
  230.         or      BYTE PTR CS:Step_Flg,STOP    ; set flag to stop and display
  231.  
  232.         include test13.asm
  233. ;
  234.         mov     AH,4ch              ; terminate
  235.         mov     AL,00
  236.         int     21h
  237. ELSE
  238. ;
  239. ; Terminate and stay resident
  240. ;
  241.         mov     AL,00
  242.         mov     AH,31h
  243.         mov     DX,SegEND           ; segment offset to release free memory
  244.         int     21h                 ; won't return
  245. ENDIF
  246.  
  247. ;
  248. ; Compare string in program to ID string
  249. ; Entry:
  250. ;    ES = segment of owning process
  251. ;    DS = current programs segment
  252. ;
  253. ; Return:
  254. ;    ZF = 1 if strings equal (TSR already installed)
  255. ;    ZF = 0 if not found
  256. ;
  257. Cmp_Str:
  258.         mov     SI,OFFSET Res_Str
  259.         mov     DI,SI               ; source and destination offsets the same
  260.         mov     BX,-1               ; assume not found here
  261. cmp1:
  262.         lodsb
  263.         scasb
  264.         jnz     neql
  265.         or      AL,AL               ; terminating null
  266.         jnz     cmp1
  267.         mov     BX,0                ; found string
  268. neql:
  269.         mov     AX,BX
  270.         or      AX,AX
  271.         ret
  272.  
  273. ;
  274. ; Restore vectors and free resident program area.
  275. ; Interrupts are off upon entry.
  276. ;
  277. Restore:
  278.         push    AX
  279.         push    DS
  280.         push    ES
  281. ;
  282.         mov     AX,CS
  283.         mov     DS,AX               ; load my data segment
  284. ;
  285.         mov     AX,0
  286.         mov     ES,AX
  287.         mov     AX,Save13           ; restore INT vectors
  288.         mov     ES:[INT13OFF],AX
  289.         mov     AX,Save13+2
  290.         mov     ES:[INT13OFF+2],AX
  291.  
  292. IFE TESTING
  293.         mov     AX,Save28
  294.         mov     ES:[INT28OFF],AX
  295.         mov     AX,Save28+2
  296.         mov     ES:[INT28OFF+2],AX
  297. ;
  298.         mov     AX,Save1c
  299.         mov     ES:[INT1cOFF],AX
  300.         mov     AX,Save1c+2
  301.         mov     ES:[INT1cOFF+2],AX
  302. ENDIF
  303.  
  304. ;
  305. ; Free allocated memory from environment and this program
  306. ;
  307.         mov     ES,SegEnv
  308.         mov     AH,49h
  309.         int     21h
  310. ;
  311.         mov     ES,SegPSP           ; start of this programs segment
  312.         mov     AH,49h
  313.         int     21h
  314. ;
  315.         pop     ES
  316.         pop     DS
  317.         pop     AX
  318.         ret
  319.  
  320. ;
  321. ; INT 1ch will be redirected to here each time a timer tick occurs.
  322. ; Do keyboard BIOS call to get state of control and shift keys.
  323. ; If both LEFT and RIGHT shift keys down, enable the Int 13 intercept code.
  324. ; If CONTROL key and LEFT and RIGHT shift keys down, set the terminate flag.
  325. ; On the next Int 28h call by DOS, we will remove this program from memory.
  326. ;
  327. New1c:
  328.        push     AX
  329.        mov      AH,02               ; get shift status
  330.        int      16h
  331.        and      AL,07               ; save control, left and right shift status
  332.        cmp      AL,03               ; are they both down?
  333.        jnz      tstctl              ; jump if no
  334.        or       BYTE PTR CS:Step_Flg,STOP    ; set flag to stop and display Int 13h
  335. tstctl:
  336.        cmp      AL,07               ; three keys down?
  337.        jnz      n1cout
  338.        or       BYTE PTR CS:Step_Flg,TERM    ; set terminate flag
  339. n1cout:
  340.        pop      AX
  341.        jmp      CS:[DWORD PTR Save1c]        ; continue in the chain
  342.  
  343. ;
  344. ; The DOS idle loop will be redirected to here.
  345. ; Check for TERMINATE bit set. If so, free all memory used by this TSR program
  346. ; and restore all vectors to their original values.
  347. ;
  348. New28:
  349.        test     BYTE PTR CS:Step_Flg,TERM
  350.        jz       n28out
  351.        call     Restore
  352.        cli
  353. n28out:
  354.        jmp      CS:[DWORD PTR Save28]        ; continue in the chain
  355.  
  356. ;
  357. ; INT 13h will be redirected to here
  358. ;
  359. New13:
  360.         push    AX                  ; use USERS'S stack for first 3 words
  361.         push    DS
  362.         pushf                       ; push them but we don't need them here
  363. ;
  364.         cli
  365.         mov     AX,CS               ; now switch to internal stack
  366.         mov     DS,AX
  367.         mov     SSsave,SS
  368.         mov     SPsave,SP
  369.         mov     SS,AX
  370.         mov     SP,OFFSET Pstack
  371.         sti
  372. ;
  373.         push    ES
  374.         push    BP
  375.         push    SI
  376.         push    DI
  377.         push    DX
  378.         push    CX
  379.         push    BX
  380.         mov     BP,SP               ; save base pointer to display reg's
  381.         mov     ES,AX
  382.         test    BYTE PTR Step_Flg,STOP    ; should we stop and display?
  383.         jz      norun               ; no, restore registers and leave
  384. ;
  385. ; Recover registers on USER'S stack
  386. ;
  387.         push    ES
  388.         les     BX,Ssave
  389.         mov     AX,ES:[BX+2]        ; get DS
  390.         mov     DSsave,AX
  391.         mov     AX,ES:[BX+4]        ; get AX
  392.         mov     AXsave,AX
  393.         mov     Last_FC,AH          ; save as last function code
  394.         mov     AX,ES:[BX+6]        ; get IP
  395.         mov     IPsave,AX
  396.         mov     AX,ES:[BX+8]        ; get CS
  397.         mov     CSsave,AX
  398.         mov     AX,ES:[BX+10]       ; get FLAGS on entry
  399.         mov     FLsave,AX
  400.         pop     ES
  401. ;
  402.         cld                         ; clear direction flag for string operations
  403.         test    BYTE PTR Skip_Flg,0ffh    ; skip certain functions?
  404.         jz      noskip              ; no, continue
  405.         mov     AX,AXsave           ; get USER's AX register with function code
  406.         cmp     AH,Skip_Typ         ; compare upper half to type to skip
  407.         jz      norun               ; don't want to break on this one again
  408.         mov     BYTE PTR Skip_Flg,00      ; skip flag was set but this is new
  409.                                     ;  function, so break from now on
  410. noskip:
  411.         call    Open_Window
  412.         call    Show_Func           ; show function number
  413.         call    Disp_Text           ; display description of BIOS function
  414.         call    Show_Help
  415. ;
  416.         call    Get_Key             ; wait for a key pressed
  417.         call    Disp_Key            ; dispatch to key handler
  418.         jc      noskip              ; if carry set, need to redisplay window
  419.         call    Close_Window
  420. norun:
  421.         pop     BX
  422.         pop     CX
  423.         pop     DX
  424.         pop     DI
  425.         pop     SI
  426.         pop     BP
  427.         pop     ES
  428.         cli
  429.         mov     SS,SSsave           ; switch back to user's stack
  430.         mov     SP,SPsave
  431. ;
  432.         mov     AX,FLsave           ; get original user's flags before INT 13h
  433.         push    AX                  ; sneak them into flag register
  434.         popf
  435. ;
  436.         pop     AX                  ; dummy pop to get flags off stack
  437.         pop     DS                  ; restore registers left on user's stack
  438.         pop     AX                  ; now get real AX
  439.  
  440. IFE TESTING
  441.         pushf
  442.         cli                         ; give interrupt code IF = 0 like normal
  443.         call    CS:[DWORD PTR Save13]
  444. ENDIF
  445.  
  446.         push    AX                  ; use USERS'S stack for first 3 words
  447.         push    DS
  448.         pushf                       ; they will get used this time
  449. ;
  450.         cli
  451.         mov     AX,CS               ; now switch to internal stack
  452.         mov     DS,AX
  453.         mov     SSsave,SS
  454.         mov     SPsave,SP
  455.         mov     SS,AX
  456.         mov     SP,OFFSET Pstack
  457.         sti
  458. ;
  459.         push    ES
  460.         push    BP
  461.         push    SI
  462.         push    DI
  463.         push    DX
  464.         push    CX
  465.         push    BX
  466.         mov     BP,SP               ; save base pointer to display reg's
  467.         mov     ES,AX
  468.         cld                         ; clear direction flag for string operations
  469. ;
  470. ; Recover registers on USER'S stack
  471. ;
  472.         push    ES
  473.         les     BX,Ssave
  474.         mov     AX,ES:[BX+0]        ; get FLAGS on exit
  475.         mov     FLsave,AX
  476.         mov     AX,ES:[BX+2]        ; get DS
  477.         mov     DSsave,AX
  478.         mov     AX,ES:[BX+4]        ; get AX
  479.         mov     AXsave,AX
  480.         mov     AX,ES:[BX+6]        ; get IP
  481.         mov     IPsave,AX
  482.         mov     AX,ES:[BX+8]        ; get CS
  483.         mov     CSsave,AX
  484.         pop     ES
  485. ;
  486.         xor     AL,AL
  487.         xchg    AL,Ret_Flg          ; read value and clear flag for next time
  488.         test    AL,0ffh             ; is flag set to display return value?
  489.         jz      nostop
  490. ;
  491.         call    Open_Window
  492.         call    Show_Func           ; show function number
  493.         call    Disp_Ret            ; display return code in AX and flags
  494.         call    Get_Key             ; wait for a key pressed
  495.         call    Close_Window
  496. nostop:
  497.         pop     BX
  498.         pop     CX
  499.         pop     DX
  500.         pop     DI
  501.         pop     SI
  502.         pop     BP
  503.         pop     ES
  504.         cli
  505.         mov     SS,SSsave
  506.         mov     SP,SPsave
  507.         popf
  508.         pop     DS
  509.         pop     AX
  510.         retf    2
  511.  
  512. ;
  513. ; Display return code in AX, carry and zero flags
  514. ;
  515. Disp_Ret:
  516.         mov     CX,0301h
  517.         mov     DX,OFFSET RCStr
  518.         mov     DI,14
  519.         mov     AX,AXsave
  520.         call    OutWord
  521. ;
  522.         mov     DX,OFFSET CFStr
  523.         mov     DI,14
  524.         add     DI,DX
  525.         mov     AL,'0'
  526.         test    FLsave,0001         ; carry flag is least significant bit
  527.         jz      dcy
  528.         inc     AL                  ; carry was set so change to '1'
  529. dcy:
  530.         mov     [DI],AL             ; store it in string
  531.         add     CX,0100h            ; move cursor position
  532.         call    Disp_Str
  533. ;
  534.         mov     DX,OFFSET ZFStr
  535.         mov     DI,14
  536.         add     DI,DX
  537.         mov     AL,'0'
  538.         test    FLsave,0040h        ; test zero flag
  539.         jz      dzf
  540.         inc     AL                  ; zero was set so change to '1'
  541. dzf:
  542.         mov     [DI],AL             ; store it in string
  543.         add     CX,0100h            ; move cursor position
  544.         call    Disp_Str
  545. ;
  546.         mov     CX,0a0ah            ; display some help
  547.         mov     DX,OFFSET HlpStr5
  548.         mov     AH,YELLOW
  549.         call    WPrint
  550. ;
  551.         mov     CX,0b0bh            ; move cursor position
  552.         mov     DX,OFFSET HlpStr6
  553.         mov     AH,YELLOW
  554.         call    WPrint
  555.         ret
  556.  
  557. ;
  558. ; Display function code description in window
  559. ;
  560. Show_Func:
  561.         mov     CX,0007h            ; cursor position - row, col
  562.         mov     DX,OFFSET FCStr     ; message address
  563.         mov     DI,DX
  564.         add     DI,19               ; offset this many into string
  565.         mov     AL,Last_FC          ; get last function code
  566.         call    Shexbyt             ; convert it to ASCII
  567.         mov     BX,OFFSET W1        ; window
  568.         mov     AH,YELLOW           ; attribute
  569.         call    WPrint
  570.         ret
  571.  
  572. ;
  573. ; Display input parameters
  574. ;
  575. Disp_Parms:
  576.         call    Disp_Drv            ; show drive number
  577.         call    Disp_Head           ; head number
  578.         call    Disp_Trk            ; track number
  579.         call    Disp_Sec            ; sector number
  580.         ret
  581.  
  582. ;
  583. ; Display input parameters for Hard Disk calls
  584. ; Displays "CYLINDER" instead of "TRACK"
  585. ;
  586. Disp_HD_Parms:
  587.         call    Disp_Drv
  588.         call    Disp_Head
  589.         call    Disp_Cyl            ; show cylinder number
  590.         ret
  591.  
  592. ;
  593. ; Display Drive ID
  594. ;
  595. Disp_Drv:
  596.         mov     CX,0401h
  597.         mov     DX,OFFSET DrvStr
  598.         mov     DI,DX
  599.         add     DI,8
  600.         mov     AX,[BP+REGDX]       ; DL register has drive #
  601.         call    Shexbyt
  602.         mov     AH,HIWHITE
  603.         call    WPrint
  604.         ret
  605.  
  606. ;
  607. ; Display Head #
  608. ;
  609. Disp_Head:
  610.         add     CX,0100h
  611.         mov     DX,OFFSET HedStr
  612.         mov     DI,DX
  613.         add     DI,8
  614.         mov     AX,[BP+REGDX]       ; DH register has head #
  615.         mov     AL,AH
  616.         call    Sdecbyt
  617.         mov     AH,HIWHITE
  618.         call    WPrint
  619.         ret
  620.  
  621. ;
  622. ; Display Track #
  623. ;
  624. Disp_Trk:
  625.         add     CX,0100h
  626.         mov     DX,OFFSET TrkStr
  627.         mov     DI,DX
  628.         add     DI,7
  629.         mov     AX,[BP+REGCX]       ; CH register has track #
  630.         mov     AL,AH
  631.         xor     AH,AH               ; clear upper half
  632.         call    HextoDec
  633.         dec     SI                  ; back up to get three chars instead
  634.         movsb                       ; of normal two
  635.         movsb
  636.         movsb
  637.         mov     AH,HIWHITE
  638.         call    WPrint
  639.         ret
  640.  
  641. ;
  642. ; Display Cylinder #
  643. ;
  644. Disp_Cyl:
  645.         add     CX,0100h
  646.         mov     DX,OFFSET CylStr
  647.         mov     DI,DX
  648.         add     DI,7
  649.         mov     AX,[BP+REGCX]       ; CH register has cylinder #
  650.         mov     AL,AH
  651.         xor     AH,AH               ; clear upper half
  652.         call    HextoDec
  653.         dec     SI
  654.         movsb
  655.         movsb
  656.         movsb
  657.         mov     AH,HIWHITE
  658.         call    WPrint
  659.         ret
  660.  
  661. ;
  662. ; Display Sector #
  663. ;
  664. Disp_Sec:
  665.         add     CX,0100h
  666.         mov     DX,OFFSET SecStr
  667.         mov     DI,DX
  668.         add     DI,8
  669.         mov     AX,[BP+REGCX]       ; CL register has sector #
  670.         call    Sdecbyt
  671.         mov     AH,HIWHITE
  672.         call    WPrint
  673.         ret
  674.  
  675. ;
  676. ; Display HELP in Window
  677. ;
  678. Show_Help:
  679.         mov     CX,0a03h            ; cursor position - row, col
  680.         mov     AH,LTRED            ; attribute for char
  681.         mov     AL,'S'
  682.         call    WChar               ; write one character with attribute
  683. ;
  684.         add     CX,0001h            ; add 1 to column number
  685.         mov     DX,OFFSET HlpStr1   ; message address
  686.         mov     AH,WHITE
  687.         call    WPrint
  688. ;
  689.         add     CX,0012h            ; move column number
  690.         mov     AH,LTRED            ; attribute for char
  691.         mov     AL,'R'
  692.         call    WChar               ; write one character with attribute
  693. ;
  694.         add     CX,0001h            ; move column number
  695.         mov     DX,OFFSET HlpStr2
  696.         mov     AH,WHITE
  697.         call    WPrint
  698. ;
  699.         mov     CX,0b01h            ; cursor position - row, col
  700.         mov     AH,LTRED
  701.         mov     AL,'E'
  702.         call    WChar
  703. ;
  704.         add     CX,0001h
  705.         mov     AH,LTRED
  706.         mov     AL,'S'
  707.         call    WChar
  708. ;
  709.         add     CX,0001h
  710.         mov     AH,LTRED
  711.         mov     AL,'C'
  712.         call    WChar
  713. ;
  714.         add     CX,0001h
  715.         mov     DX,OFFSET HlpStr3
  716.         mov     AH,WHITE
  717.         call    WPrint
  718. ;
  719.         add     CX,000dh
  720.         mov     AH,LTRED
  721.         mov     AL,18h              ; up arrow
  722.         call    WChar
  723. ;
  724.         add     CX,0001h
  725.         mov     AH,LTRED
  726.         mov     AL,19h              ; down arrow
  727.         call    WChar
  728. ;
  729.         add     CX,0001h
  730.         mov     AH,LTRED
  731.         mov     AL,1bh              ; left arrow
  732.         call    WChar
  733. ;
  734.         add     CX,0001h
  735.         mov     AH,LTRED
  736.         mov     AL,1ah              ; right arrow
  737.         call    WChar
  738. ;
  739.         add     CX,0001h
  740.         mov     DX,OFFSET HlpStr4
  741.         mov     AH,WHITE
  742.         call    WPrint
  743.         ret
  744.  
  745. ;
  746. ; HextoDec converts a word in AX to an ASCII string
  747. ; Entry:
  748. ;      AX = word to convert
  749. ; Exit:
  750. ;      SI = Pointer to last two character of ASCII string in 'Astr'
  751. ;
  752. HextoDec:
  753.          push   AX
  754.          push   CX
  755.          push   DX
  756.          push   DI
  757. ;
  758.          mov    DI,OFFSET Astr
  759.          mov    CX,10000
  760.          xor    DX,DX
  761.          div    CX                  ; num / 10000
  762.          add    AL,'0'
  763.          stosb
  764.          mov    AX,DX
  765.          mov    CX,1000
  766.          xor    DX,DX
  767.          div    CX                  ; num / 1000
  768.          add    AL,'0'
  769.          stosb
  770.          mov    AX,DX
  771.          mov    CX,100
  772.          xor    DX,DX
  773.          div    CX                  ; num / 100
  774.          add    AL,'0'
  775.          stosb
  776.          mov    AX,DX
  777.          mov    CX,10
  778.          xor    DX,DX
  779.          div    CX                  ; num / 10
  780.          add    AL,'0'
  781.          stosb
  782.          mov    AX,DX
  783.          add    AL,'0'
  784.          stosb
  785.          xor    AL,AL               ; <NULL> terminator in string
  786.          stosb
  787.          sub    DI,3                ; back up pointer
  788.          mov    SI,DI
  789. ;
  790.          pop    DI
  791.          pop    DX
  792.          pop    CX
  793.          pop    AX
  794.          ret
  795.  
  796. ;
  797. ; Display the text description of the current BIOS function code
  798. ;
  799. Disp_Text:
  800.         mov     CX,LENFC / 6        ; number of entries
  801.         mov     AX,AXsave           ; get user's function code
  802.         cmp     AH,CL               ; is it in range?
  803.         jnb     not_fnd             ; jump if no
  804.         mov     DI,OFFSET FCtbl
  805. cmpdt:
  806.         cmp     AH,[DI+1]           ; is this the right function?
  807.         jz      dtexec
  808.         add     DI,6                ; no, point to next
  809.         loop    cmpdt
  810. not_fnd:
  811.         mov     DX,OFFSET STRUN
  812.         mov     CX,0201h
  813.         call    Disp_Str
  814.         ret
  815.  
  816. dtexec:
  817.         mov     CX,0201h            ; row, col to position string
  818.         mov     DX,[DI+2]           ; get pointer to string
  819.         call    [WORD PTR DI+4]     ; go to display routine
  820.         ret
  821.  
  822. ;
  823. ; Display string of DOS function code description
  824. ;
  825. ; Entry:
  826. ;       DX = pointer to string
  827. ;       CX = Row, Col
  828. ;
  829. Disp_Str:
  830.         mov     BX,OFFSET W1
  831.         mov     AH,HIWHITE
  832.         call    WPrint
  833.         ret
  834.  
  835. ;
  836. ; Routines to build string for display - some values need to be filled in
  837. ; Entry:
  838. ;       DX = pointer to string
  839. ;       CX = Row, Col in window
  840. ;
  841. ; Read sectors
  842. ;
  843. Disp_02:
  844.         mov     DI,5
  845.         add     DI,DX
  846.         mov     AX,AXsave           ; AL has number of sectors to read
  847.         call    Sdecbyt             ; convert it to ASCII decimal
  848.         call    Disp_Str
  849.         call    Disp_Parms          ; show input parameters
  850.         call    Disp_Buf            ; show buffer addr in ES:BX
  851.         ret
  852. ;
  853. ; Write sectors
  854. ;
  855. Disp_03:
  856.         mov     DI,6
  857.         add     DI,DX
  858.         mov     AX,AXsave           ; AL has number of sectors to write
  859.         call    Sdecbyt             ; convert it to ASCII decimal
  860.         call    Disp_Str
  861.         call    Disp_Parms          ; show input parameters
  862.         call    Disp_Buf
  863.         ret
  864.  
  865. ;
  866. ; Verify sectors
  867. ;
  868. Disp_04:
  869.         mov     DI,7
  870.         add     DI,DX
  871.         mov     AX,AXsave           ; AL has number of sectors to write
  872.         call    Sdecbyt             ; convert it to ASCII decimal
  873.         call    Disp_Str            ; show function description
  874.         call    Disp_Parms          ; show input parameters
  875.         ret
  876.  
  877. ;
  878. ; Format track
  879. ;
  880. Disp_05:
  881.         call    Disp_Str
  882.         call    Disp_Parms
  883.         call    Disp_Buf
  884.         ret
  885.  
  886. ;
  887. ; Read and Write Long
  888. ;
  889. Disp_0a:
  890. Disp_0b:
  891.         call    Disp_Str
  892.         call    Disp_HD_Parms       ; show Drive, Head and Cylinder
  893.         call    Disp_Sec            ; show Sector #
  894.         call    Disp_Buf            ;  and Buffer address
  895.         ret
  896.  
  897. ;
  898. ; Seek to Cylinder
  899. ;
  900. Disp_0c:
  901.         call    Disp_Str
  902.         call    Disp_HD_Parms       ; show Drive, Head and Cylinder
  903.         ret
  904.  
  905. ;
  906. ; Alternate Disk Reset
  907. ;
  908. Disp_0d:
  909.         call    Disp_Str
  910.         call    Disp_Drv           ; show drive ID
  911.         ret
  912.  
  913. ;
  914. ; Test for Drive Ready
  915. ;
  916. Disp_10:
  917.         call    Disp_Str
  918.         call    Disp_Drv
  919.         ret
  920.  
  921. ;
  922. ; Recalibrate Drive
  923. ;
  924. Disp_11:
  925.         call    Disp_Str
  926.         call    Disp_Drv
  927.         ret
  928.  
  929. ;
  930. ; Get Disk Type
  931. ;
  932. Disp_15:
  933.         call    Disp_Str
  934.         call    Disp_Drv
  935.         ret
  936.  
  937. ;
  938. ; Set Disk Type
  939. ;
  940. Disp_17:
  941.         mov     DI,17
  942.         add     DI,DX
  943.         mov     AX,AXsave           ; AL has disk type
  944.         call    Shexbyt
  945.         call    Disp_Str
  946. ;
  947.         mov     AX,AXsave
  948.         mov     DX,OFFSET Str170
  949.         cmp     AL,00               ; no disk?
  950.         jz      d17shw
  951.         mov     DX,OFFSET Str171
  952.         cmp     AL,01               ; regular diskette?
  953.         jz      d17shw
  954.         mov     DX,OFFSET Str173
  955.         cmp     AL,03               ; high capacity diskette?
  956.         jnz     d17drv
  957. d17shw:
  958.         add     CX,0100h
  959.         call    Disp_Str
  960. d17drv:
  961.         call    Disp_Drv
  962.         ret
  963.  
  964. ;
  965. ; Display ES:BX registers
  966. ;
  967. Disp_Buf:
  968.         mov     DX,OFFSET BufStr    ; show buffer address
  969.         mov     DI,17
  970.         add     CX,0100h
  971.         call    OutESBX
  972.         ret
  973.  
  974. ;
  975. ; Convert users's ES and BX to ASCII, imbed them in target string
  976. ; Entry:
  977. ;      DX = pointer to string
  978. ;      DI = offset where to put converted ES:BX
  979. ;      CX = Row, Col
  980. ;
  981. OutESBX:
  982.         add     DI,DX
  983.         mov     AX,[BP+REGES]       ; get user's ES
  984.         call    Shexwrd
  985.         inc     DI                  ; skip past ':'
  986.         mov     AX,[BP+REGBX]       ; get user's BX
  987.         call    Shexwrd
  988.         call    Disp_Str
  989.         ret
  990.  
  991. ;
  992. ; Convert word in AX to ASCII, imbed it in target string
  993. ; Entry:
  994. ;      AX = word to convert
  995. ;      CX = row, col
  996. ;      DX = pointer to string
  997. ;      DI = offset where to put converted AX
  998. ;
  999. OutWord:
  1000.         add     DI,DX
  1001.         call    Shexwrd
  1002.         call    Disp_Str
  1003.         ret
  1004.  
  1005.  
  1006. Open_Window:
  1007.         push    BP
  1008.         push    ES
  1009. ;
  1010. ; Calculate current page offset each time since it can change at any time
  1011. ;
  1012.         mov     AH,0fh              ; get current video state
  1013.         int     10h
  1014.         mov     CL,BH               ; returns BH = active page #
  1015.         xor     CH,CH
  1016.         mov     AX,0100h            ; page length in paragraphs
  1017.         mul     cx
  1018.         add     AX,Scrseg           ; add base segment of screen
  1019.         mov     Pageseg,AX
  1020. ;
  1021. ; Save current contents of window area
  1022. ;
  1023.         mov     BX,OFFSET W1        ; window parameters
  1024.         mov     SI,[BX].startmem    ; screen addr of start of window
  1025.         mov     DX,[BX].height
  1026.         mov     ES,Winseg           ; point to allocated memory block
  1027.         mov     DI,0000
  1028. saverow:
  1029.         push    DS
  1030.         mov     CX,[BX].xwidth
  1031.         mov     DS,Pageseg          ; get screen segment
  1032.         push    SI                  ; save screen offset
  1033. rep     movsw                       ; do word to get char and attribute
  1034.         pop     SI
  1035.         pop     DS
  1036.         add     SI,BytesPL          ; next row down
  1037.         dec     DX
  1038.         jnz     saverow
  1039. ;
  1040. ; Draw window
  1041. ;
  1042.         mov     ES,Pageseg          ; get screen segment
  1043.         mov     DI,[BX].startmem    ; physical addr of start of window
  1044.         mov     AH,HIWHITE
  1045. ;
  1046. ; Draw top border
  1047. ;
  1048.         push    DI
  1049.         mov     AL,ULC              ; write upper left corner
  1050.         stosw
  1051.         mov     CX,[BX].xwidth
  1052.         sub     CX,2
  1053.         mov     AL,BRDROW
  1054. rep     stosw
  1055.         mov     AL,URC              ; write upper right corner
  1056.         stosw
  1057.         pop     DI
  1058.         add     DI,BytesPL          ; next row down
  1059. ;
  1060. ; Draw middle of window
  1061. ;
  1062.         mov     DX,[BX].height
  1063.         sub     DX,2
  1064. winrows:
  1065.         push    DI
  1066.         mov     AL,BRDCOL           ; left border column
  1067.         stosw
  1068.         mov     CX,[BX].xwidth
  1069.         sub     CX,2
  1070.         mov     AL,BLANK
  1071. rep     stosw
  1072.         mov     AL,BRDCOL           ; right border column
  1073.         stosw
  1074.         pop     DI
  1075.         add     DI,BytesPL          ; next row down
  1076.         dec     DX
  1077.         jnz     winrows
  1078. ;
  1079. ; Draw bottom border
  1080. ;
  1081.         push    DI
  1082.         mov     AL,LLC              ; write lower left corner
  1083.         stosw
  1084.         mov     CX,[BX].xwidth
  1085.         sub     CX,2
  1086.         mov     AL,BRDROW
  1087. rep     stosw
  1088.         mov     AL,LRC              ; write lower right corner
  1089.         stosw
  1090.         pop     DI
  1091. ;
  1092.         pop     ES
  1093.         pop     BP
  1094.         ret
  1095.  
  1096.  
  1097. Close_Window:
  1098.         push    ES
  1099.         mov     BX,OFFSET W1
  1100.         mov     DI,[BX].startmem    ; physical addr of screen area
  1101.         mov     ES,Pageseg          ; point to allocated memory block
  1102.         mov     SI,0000             ; start of save memory block
  1103.         mov     DX,[BX].height
  1104. resrow:
  1105.         push    DS
  1106.         mov     CX,[BX].xwidth
  1107.         mov     DS,Winseg           ; get saved memory segment
  1108.         push    DI                  ; save screen offset
  1109. rep     movsw                       ; do word to get char and attribute
  1110.         pop     DI
  1111.         pop     DS
  1112.         add     DI,BytesPL          ; next row down
  1113.         dec     DX
  1114.         jnz     resrow
  1115.         pop     ES
  1116.         ret
  1117.  
  1118. ;
  1119. ; Print a string in window.
  1120. ; Entry:
  1121. ;        CX = Row, Col position relative to start of window
  1122. ;        BX = Window pointer
  1123. ;        AH = Attribute
  1124. ;        DX = addr of string
  1125. ;
  1126. WPrint:
  1127.         push    ES
  1128.         call    GetRC               ; convert to row, col in DI
  1129.         mov     ES,Pageseg
  1130.         mov     SI,DX               ; move string address
  1131. wpwrt:
  1132.         cmp     BYTE PTR [SI],00    ; test for string terminator <NULL>
  1133.         jz      wpexit
  1134.         lodsb
  1135.         stosw
  1136.         jmp     wpwrt
  1137. wpexit:
  1138.         pop     ES
  1139.         ret
  1140.  
  1141. ;
  1142. ; Write one character and attribute to window
  1143. ;
  1144. ; Entry:
  1145. ;        CX = Row, Col position relative to start of window
  1146. ;        BX = Window pointer
  1147. ;        AH = attr
  1148. ;        AL = char
  1149. ;
  1150. WChar:
  1151.         push    ES
  1152.         call    GetRC               ; convert to row, col in DI
  1153.         mov     ES,Pageseg
  1154.         stosw
  1155.         pop     ES
  1156.         ret
  1157.  
  1158. ;
  1159. ; Convert row, col in CX to physical addr in DI
  1160. ;
  1161. GetRC:
  1162.         push    AX
  1163.         push    DX
  1164.         mov     DI,[BX].startmem    ; physical start of window memory
  1165.         add     DI,BytesPL          ; go down a row
  1166.         add     DI,2                ; go in one char, this is 0,0
  1167.         mov     AL,CH
  1168.         xor     AH,AH               ; AX = relative row number
  1169.         mul     BytesPL             ; this clobbers DX
  1170.         add     DI,AX
  1171.         mov     AX,CX               ; restore coordinates
  1172.         xor     AH,AH               ; AX = relative col number
  1173.         shl     AX,1                ; times 2 for attribute
  1174.         add     DI,AX
  1175.         pop     DX
  1176.         pop     AX
  1177.         ret
  1178.  
  1179. ;
  1180. ; STORE HEX WORD
  1181. ; Convert a hex word to ASCII and store it in destination string
  1182. ; Entry:
  1183. ;        AX = Word to convert
  1184. ;        DI = destination pointer
  1185. ;
  1186. Shexwrd:
  1187.         xchg    AL,AH               ; convert upper half first
  1188.         call    Shexbyt
  1189.         xchg    AL,AH               ; convert lower half
  1190.         call    Shexbyt
  1191.         ret
  1192.  
  1193. ;
  1194. ; STORE HEX BYTE
  1195. ; Convert a hex byte to ASCII and store it in destination string
  1196. ; Entry:
  1197. ;        AL = Byte to convert
  1198. ;        DI = destination pointer
  1199. ;
  1200. Shexbyt:
  1201.         push    AX
  1202.         mov     AH,AL               ; save temporarily
  1203.         shr     AL,1
  1204.         shr     AL,1
  1205.         shr     AL,1
  1206.         shr     AL,1
  1207.         cmp     AL,10
  1208.         jb      wh1
  1209.         add     AL,07
  1210. wh1:
  1211.         add     AL,'0'
  1212.         stosb
  1213.         mov     AL,AH
  1214.         and     AL,0fh
  1215.         cmp     AL,10
  1216.         jb      wh2
  1217.         add     AL,07
  1218. wh2:
  1219.         add     AL,'0'
  1220.         stosb
  1221.         pop     AX
  1222.         ret
  1223.  
  1224. ;
  1225. ; STORE DECIMAL BYTE
  1226. ; Convert a hex byte to ASCII decimal and store it in destination string
  1227. ; Entry:
  1228. ;        AL = Byte to convert
  1229. ;        DI = destination pointer
  1230. ;
  1231. Sdecbyt:
  1232.         and     AX,00ffh            ; mask off upper half
  1233.         call    HextoDec
  1234.         movsb                       ; copy 2 chars to destination string
  1235.         movsb
  1236.         ret
  1237.  
  1238. ;
  1239. ; Check if key pressed requires special handling
  1240. ;
  1241. ; Entry:
  1242. ;      AX = key pressed
  1243. ;
  1244. Disp_Key:
  1245.         mov     DI,OFFSET Keytbl    ; keys and subroutine addresses
  1246.         mov     CX,LENKTAB / 4      ; number of entries
  1247. cmpdk:
  1248.         cmp     AX,[DI]             ; is key in table?
  1249.         jz      dkexec
  1250.         add     DI,4                ; no, point to next key value
  1251.         loop    cmpdk
  1252.         clc                         ; carry clear means exit upon return
  1253.         ret
  1254. dkexec:
  1255.         add     DI,2
  1256.         call    [WORD PTR DI]
  1257.         ret
  1258.  
  1259. ;
  1260. ; Table of keys to watch for followed by the address of the routine to execute
  1261. ;
  1262. Keytbl  dw      ESCAPE,     DO_Esc
  1263.         dw      BIGS,       Do_Skey
  1264.         dw      SMALLS,     Do_Skey
  1265.         dw      BIGR,       Do_Rkey
  1266.         dw      SMALLR,     Do_Rkey
  1267.         dw      UPARROW,    Do_Up
  1268.         dw      DOWNARROW,  Do_Down
  1269.         dw      LEFTARROW,  Do_Left
  1270.         dw      RIGHTARROW, Do_Right
  1271.         dw      HOME,       Do_Home
  1272.         dw      XEND,       Do_End
  1273.         dw      PGUP,       Do_Pgup
  1274.         dw      PGDN,       Do_Pgdn
  1275. LENKTAB EQU     $ - Keytbl
  1276.  
  1277. ;
  1278. ; If ESC key, clear flag so Int 13h will not be stopped each time
  1279. ;
  1280. Do_Esc:
  1281.         and     BYTE PTR Step_Flg,255-STOP
  1282.         clc                         ; carry clear means exit upon return
  1283.         ret
  1284.  
  1285. ;
  1286. ; 'S' key - skip successive functions of current type.
  1287. ; Return to intercepting calls when something new comes along.
  1288. ;
  1289. Do_Skey:
  1290.         mov     AL,0ffh
  1291.         mov     Skip_Flg,AL         ; set flag to show we should skip something
  1292.         mov     AL,Last_FC          ; get current function code
  1293.         mov     Skip_Typ,AL         ; save it
  1294.         clc                         ; carry clear means exit upon return
  1295.         ret
  1296.  
  1297. ;
  1298. ; 'R' key - stop after INT 13h call and let user see results
  1299. ;
  1300. Do_Rkey:
  1301.         mov     AL,0ffh
  1302.         mov     Ret_Flg,AL          ; set flag
  1303.         clc                         ; carry clear means exit upon return
  1304.         ret
  1305.  
  1306. ;
  1307. ; DO_Up - move window up one line
  1308. ;
  1309. Do_Up:
  1310.         mov     BX,OFFSET W1
  1311.         call    Close_Window
  1312.         mov     AX,[BX].leftrow
  1313.         or      AX,AX               ; already at top of screen?
  1314.         jz      upexit
  1315.         dec     [BX].leftrow
  1316.         dec     [BX].rightrow
  1317.         call    Window_Parms        ; recalculate parameters
  1318. upexit:
  1319.         stc                         ; don't exit upon return
  1320.         ret
  1321.  
  1322. ;
  1323. ; DO_Down - move window down one line
  1324. ;
  1325. Do_Down:
  1326.         mov     BX,OFFSET W1
  1327.         call    Close_Window
  1328.         mov     AX,[BX].rightrow
  1329.         cmp     AX,24               ; already at bottom of screen?
  1330.         jz      dnexit
  1331.         inc     [BX].leftrow
  1332.         inc     [BX].rightrow
  1333.         call    Window_Parms        ; recalculate parameters
  1334. dnexit:
  1335.         stc                         ; don't exit upon return
  1336.         ret
  1337.  
  1338. ;
  1339. ; DO_Left - move window left one column
  1340. ;
  1341. Do_Left:
  1342.         mov     BX,OFFSET W1
  1343.         call    Close_Window
  1344.         mov     AX,[BX].leftcol
  1345.         or      AX,AX               ; already at left of screen?
  1346.         jz      lfexit
  1347.         dec     [BX].leftcol
  1348.         dec     [BX].rightcol
  1349.         call    Window_Parms        ; recalculate parameters
  1350. lfexit:
  1351.         stc                         ; don't exit upon return
  1352.         ret
  1353.  
  1354. ;
  1355. ; Do_Right - move window right one column
  1356. ;
  1357. Do_Right:
  1358.         mov     BX,OFFSET W1
  1359.         call    Close_Window
  1360.         mov     AX,[BX].rightcol
  1361.         cmp     AX,79               ; already at right of screen?
  1362.         jz      rtexit
  1363.         inc     [BX].leftcol
  1364.         inc     [BX].rightcol
  1365.         call    Window_Parms        ; recalculate parameters
  1366. rtexit:
  1367.         stc                         ; don't exit upon return
  1368.         ret
  1369.  
  1370. ;
  1371. ; Do_Home - move window to upper left corner
  1372. ;
  1373. Do_Home:
  1374.         mov     BX,OFFSET W1
  1375.         call    Close_Window
  1376.         xor     AX,AX
  1377.         mov     [BX].leftrow,AX
  1378.         mov     [BX].leftcol,AX
  1379. ;
  1380.         mov     AX,[BX].leftrow
  1381.         add     AX,[BX].height
  1382.         dec     AX
  1383.         mov     [BX].rightrow,AX
  1384. ;
  1385.         mov     AX,[BX].leftcol
  1386.         add     AX,[BX].xwidth
  1387.         dec     AX
  1388.         mov     [BX].rightcol,AX
  1389. ;
  1390.         call    Window_Parms        ; recalculate parameters
  1391.         stc                         ; don't exit upon return
  1392.         ret
  1393.  
  1394. ;
  1395. ; Do_End - move window to lower left corner
  1396. ;
  1397. Do_End:
  1398.         mov     BX,OFFSET W1
  1399.         call    Close_Window
  1400.         mov     AX,24
  1401.         mov     [BX].rightrow,AX
  1402.         xor     AX,AX
  1403.         mov     [BX].leftcol,AX
  1404. ;
  1405.         mov     AX,[BX].rightrow
  1406.         sub     AX,[BX].height
  1407.         inc     AX
  1408.         mov     [BX].leftrow,AX
  1409. ;
  1410.         mov     AX,[BX].leftcol
  1411.         add     AX,[BX].xwidth
  1412.         dec     AX
  1413.         mov     [BX].rightcol,AX
  1414. ;
  1415.         call    Window_Parms        ; recalculate parameters
  1416.         stc                         ; don't exit upon return
  1417.         ret
  1418.  
  1419. ;
  1420. ; Do_Pgup - move window to upper right corner
  1421. ;
  1422. Do_Pgup:
  1423.         mov     BX,OFFSET W1
  1424.         call    Close_Window
  1425.         xor     AX,AX
  1426.         mov     [BX].leftrow,AX
  1427.         mov     AX,79
  1428.         mov     [BX].rightcol,AX
  1429. ;
  1430.         mov     AX,[BX].leftrow
  1431.         add     AX,[BX].height
  1432.         dec     AX
  1433.         mov     [BX].rightrow,AX
  1434. ;
  1435.         mov     AX,[BX].rightcol
  1436.         sub     AX,[BX].xwidth
  1437.         inc     AX
  1438.         mov     [BX].leftcol,AX
  1439. ;
  1440.         call    Window_Parms        ; recalculate parameters
  1441.         stc                         ; don't exit upon return
  1442.         ret
  1443.  
  1444. ;
  1445. ; Do_Pgdn - move window to lower right corner
  1446. ;
  1447. Do_Pgdn:
  1448.         mov     BX,OFFSET W1
  1449.         call    Close_Window
  1450.         mov     AX,24
  1451.         mov     [BX].rightrow,AX
  1452.         mov     AX,79
  1453.         mov     [BX].rightcol,AX
  1454. ;
  1455.         mov     AX,[BX].rightrow
  1456.         sub     AX,[BX].height
  1457.         inc     AX
  1458.         mov     [BX].leftrow,AX
  1459. ;
  1460.         mov     AX,[BX].rightcol
  1461.         sub     AX,[BX].xwidth
  1462.         inc     AX
  1463.         mov     [BX].leftcol,AX
  1464. ;
  1465.         call    Window_Parms        ; recalculate parameters
  1466.         stc                         ; don't exit upon return
  1467.         ret
  1468.  
  1469. ;
  1470. ; Wait for any key pressed
  1471. ;
  1472. Get_Key:
  1473.         push    BP                  ; just in case
  1474.         mov     AH,00
  1475.         int     16h
  1476.         pop     BP
  1477.         ret
  1478.  
  1479. ;
  1480. ; Calculate window parameters:
  1481. ;      1) Physical starting address of window
  1482. ;      2) Width of window in characters
  1483. ;      3) Height of window
  1484. ;
  1485. ; Entry:
  1486. ;      BX = window pointer
  1487. ; Exit:
  1488. ;      AX = Number of bytes contained in window
  1489. ;
  1490. Window_Parms:
  1491.         mov     AX,[BX].leftrow
  1492.         mul     BytesPL             ; multiply by bytes per line
  1493.         mov     CX,[BX].leftcol
  1494.         shl     CX,1                ; times 2 for attribute byte
  1495.         add     AX,CX
  1496.         mov     SI,AX               ; starting physical address of window
  1497.         mov     [BX].startmem,AX    ; save it for later
  1498. ;
  1499. ; Calculate size of window in bytes to allocate memory
  1500. ;
  1501.         mov     AX,[BX].rightcol
  1502.         inc     AX
  1503.         sub     AX,[BX].leftcol
  1504.         mov     [BX].xwidth,AX
  1505.         mov     CX,[BX].rightrow
  1506.         inc     CX
  1507.         sub     CX,[BX].leftrow
  1508.         mov     [BX].height,CX
  1509.         mul     CL                  ; AX = nbr of bytes of screen area
  1510.         shl     AX,1                ; times 2 to get attributes also
  1511.         ret
  1512.  
  1513. ;
  1514. ; Table of function codes.
  1515. ; (1st) word is DOS function code (AH),
  1516. ; (2nd) word is pointer to string to display,
  1517. ; (3rd) word is subroutine address to handle display of this type function.
  1518. ;
  1519. FCtbl:
  1520.         dw      0000h, STR00, Disp_Str
  1521.         dw      0100h, STR01, Disp_Str
  1522.         dw      0200h, STR02, Disp_02
  1523.         dw      0300h, STR03, Disp_03
  1524.         dw      0400h, STR04, Disp_04
  1525.         dw      0500h, STR05, Disp_05
  1526.         dw      0600h, STRUN, Disp_Str
  1527.         dw      0700h, STRUN, Disp_Str
  1528.         dw      0800h, STR08, Disp_Str
  1529.         dw      0900h, STR09, Disp_Str
  1530.         dw      0a00h, STR0a, Disp_0a
  1531.         dw      0b00h, STR0b, Disp_0b
  1532.         dw      0c00h, STR0c, Disp_0c
  1533.         dw      0d00h, STR0d, Disp_0d
  1534.         dw      0e00h, STRUN, Disp_Str
  1535.         dw      0f00h, STRUN, Disp_Str
  1536.         dw      1000h, STR10, Disp_10
  1537.         dw      1100h, STR11, Disp_11
  1538.         dw      1200h, STRUN, Disp_Str
  1539.         dw      1300h, STRUN, Disp_Str
  1540.         dw      1400h, STR14, Disp_Str
  1541.         dw      1500h, STR15, Disp_15
  1542.         dw      1600h, STR16, Disp_Str
  1543.         dw      1700h, STR17, Disp_17
  1544. LENFC   EQU     $ - FCtbl
  1545. ;
  1546. ;
  1547. STR00   db      'Reset Disk System'
  1548.         db      0
  1549.  
  1550. STR01   db      'Get Disk Status'
  1551.         db      0
  1552.  
  1553. STR02   db      'Read XX Disk Sector(s)'
  1554.         db      0
  1555.  
  1556. STR03   db      'Write XX Disk Sector(s)'
  1557.         db      0
  1558.  
  1559. STR04   db      'Verify XX Disk Sector(s)'
  1560.         db      0
  1561.  
  1562. STR05   db      'Format Disk Track'
  1563.         db      0
  1564.  
  1565. STR08   db      'Get Current Drive Parameters'
  1566.         db      0
  1567.  
  1568. STR09   db      'Initialize Fixed-Disk Base Tables'
  1569.         db      0
  1570.  
  1571. STR0a   db      'Read Long'
  1572.         db      0
  1573.  
  1574. STR0b   db      'Write Long'
  1575.         db      0
  1576.  
  1577. STR0c   db      'Seek to Cylinder'
  1578.         db      0
  1579.  
  1580. STR0d   db      'Alternate Disk Reset'
  1581.         db      0
  1582.  
  1583. STR10   db      'Test For Drive Ready'
  1584.         db      0
  1585.  
  1586. STR11   db      'Recalibrate Drive'
  1587.         db      0
  1588.  
  1589. STR14   db      'Controller Diagnostics'
  1590.         db      0
  1591.  
  1592. STR15   db      'Get Disk Type'
  1593.         db      0
  1594.  
  1595. STR16   db      'Change of Disk Status'
  1596.         db      0
  1597.  
  1598. STR17   db      'Set Disk Type to XXH'
  1599.         db      0
  1600.  
  1601. STR170  db      'No Disk'
  1602.         db      0
  1603.  
  1604. STR171  db      'Regular Diskette'
  1605.         db      0
  1606.  
  1607. STR173  db      'High Capacity Diskette (1.2 MB)'
  1608.         db      0
  1609.  
  1610. STRUN   db      '** Undefined Function **'
  1611.         db      0
  1612.  
  1613. ;
  1614. ; Define format of WINDOW structure
  1615. ;
  1616. Window  STRUC
  1617.    leftrow   dw     ?
  1618.    leftcol   dw     ?
  1619.    rightrow  dw     ?
  1620.    rightcol  dw     ?
  1621.    xwidth    dw     ?
  1622.    height    dw     ?
  1623.    startmem  dw     ?
  1624. Window  ENDS
  1625.  
  1626. ;
  1627. ; Allocate and initialize WINDOW parameters
  1628. ;
  1629. W1        Window     <0, 42, 13, 79, 0, 0, 0>
  1630.  
  1631. Winseg    dw     0000                ; store segment of allocated memory
  1632.                                      ;  for saving screen data
  1633. Scrseg    dw     0000                ; base segment for screen memory
  1634. Pageseg   dw     0000                ; segment after page offset factored in
  1635. BytesPL   dw     80*2                ; number of bytes per line (char + attr)
  1636. Ret_Flg   db     00                  ; 'stop on return' flag
  1637. SegEnv    dw     0000                ; segment of environment
  1638. SegPSP    dw     0000                ; segment of PSP at load time
  1639. SegEND    dw     0000                ; program segment size
  1640. Step_Flg  db     00                  ; step flag
  1641.                                      ;  stop and display if bit 0 = 1
  1642.                                      ;  terminate STEP13 if bit 1 = 1
  1643. ;
  1644. Skip_Typ  db     00                  ; type of function call to skip temporarily
  1645. Skip_Flg  db     00                  ; set if function should be skipped
  1646.  
  1647. Save13    dw     ?                   ; save original Int13 vector here, IP
  1648.           dw     ?                   ;  and SEG
  1649.  
  1650. Save28    dw     ?                   ; save original Int28 vector here, IP
  1651.           dw     ?                   ;  and SEG
  1652.  
  1653. Save1c    dw     ?                   ; save original Int1c vector here, IP
  1654.           dw     ?                   ;  and SEG
  1655.  
  1656. Ssave     LABEL  DWORD
  1657. SPsave    dw     ?                   ; save some of the user's registers here
  1658. SSsave    dw     ?                   ;  others will be on local stack
  1659.  
  1660. AXsave    dw     ?                   ; these will have been left on user's
  1661. DSsave    dw     ?                   ;  stack instead of local stack
  1662. CSsave    dw     ?
  1663. IPsave    dw     ?
  1664. FLsave    dw     ?
  1665. Last_FC   db     ?                   ; save 'AH' as last function code
  1666. ;
  1667. INITmsg   db     CR
  1668.           db     LF
  1669.           db     '*** STEP13 Version 1.0 Installed ***'
  1670.           db     CR
  1671.           db     LF
  1672.           db     LF
  1673.           db     '   Press BOTH shift keys down to enable STEP13.'
  1674.           db     CR
  1675.           db     LF
  1676.           db     '   Press CONTROL and BOTH shift keys down to remove STEP13 '
  1677.           db     'from memory.'
  1678.           db     CR
  1679.           db     LF
  1680.           db     '$'
  1681.  
  1682. ERRmsg    db     CR
  1683.           db     LF
  1684.           db     'STEP13 already installed'
  1685.           db     '$'
  1686.  
  1687. FCStr     db     'Int 13H - Function XXH'
  1688.           db     0
  1689.  
  1690. DrvStr    db     'Drive:  XXH'
  1691.           db     0
  1692.  
  1693. HedStr    db     'Head:   XX'
  1694.           db     0
  1695.  
  1696. TrkStr    db     'Track: XXX'
  1697.           db     0
  1698.  
  1699. SecStr    db     'Sector: XX'
  1700.           db     0
  1701.  
  1702. CylStr    db     'Cyl:   XXX'
  1703.           db     0
  1704.  
  1705. BufStr    db     'Buffer Address = XXXX:XXXXH'
  1706.           db     0
  1707.  
  1708. RCStr     db     'Return Code = XXXXH'
  1709.           db     0
  1710.  
  1711. CFStr     db     'Carry Flag  = X'
  1712.           db     0
  1713.  
  1714. ZFStr     db     'Zero Flag   = X'
  1715.           db     0
  1716.  
  1717. HlpStr1   db     'kip Current Func'
  1718.           db     0
  1719.  
  1720. HlpStr2   db     'eturn Code'
  1721.           db     0
  1722.  
  1723. HlpStr3   db     ' - Non Stop'
  1724.           db     0
  1725.  
  1726. HlpStr4   db     ' - Move Window'
  1727.           db     0
  1728.  
  1729. HlpStr5   db     'Press Any Key'
  1730.           db     0
  1731.  
  1732. HlpStr6   db     'To Continue'
  1733.           db     0
  1734.  
  1735. Astr      db     32 dup (0)          ; string for converting ASCII characters
  1736.  
  1737. ;
  1738. ; Local Program Stack Area
  1739. ;
  1740.           db     128 dup (?)
  1741. Pstack    EQU    $
  1742.  
  1743.  
  1744. IF TESTING
  1745.           db     128 dup (?)        ; Test Stack Area
  1746. Tstack    EQU    $
  1747.  
  1748. Buffer    db     512 dup (?)
  1749. ENDIF
  1750.  
  1751.  
  1752. PRSIZE    EQU     $
  1753.  
  1754. Code      ENDS
  1755.  
  1756.           END     Main
  1757.  
  1758.